package com.piece.core.mongo.service;

import com.piece.core.framework.constant.ApplicationConstants;
import com.piece.core.framework.enums.StatusType;
import com.piece.core.framework.support.dto.PayloadDTO;
import com.piece.core.framework.util.object.ObjectUtil;
import com.piece.core.framework.util.string.JsonUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.mongo.repository.MongoMessageLogRepository;
import com.piece.core.mongo.entity.MongoMessageLog;
import com.piece.core.framework.support.bootstrap.DataTable;
import com.piece.core.framework.support.bootstrap.QueryTable;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.util.message.MessageFactory;
import com.piece.core.framework.properties.ApplicationProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Transactional
@Service("mongoMessageLogService")
public class MongoMessageLogService {

    @Autowired
    private ApplicationProperties applicationProperties;

    @Lazy
    @Autowired
    private MessageFactory messageFactory;

    @Autowired
    private MongoMessageLogRepository mongoMessageLogRepository;

    public MongoMessageLog insert(MongoMessageLog log) {
        return mongoMessageLogRepository.save(log);
    }

    public MongoMessageLog update(MongoMessageLog log) {
        return mongoMessageLogRepository.saveOrUpdate(log.getLogId(), log);
    }

    public void delete(String id) {
        MongoMessageLog log = new MongoMessageLog();
        log.setLogId(id);
        mongoMessageLogRepository.delete(log);
    }

    public void deleteAll(String[] type) {
        if (ObjectUtil.isEmpty(type)) {
            mongoMessageLogRepository.deleteAll();
            return;
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("type").in(type));
        mongoMessageLogRepository.deleteByQuery(query);
    }

    public List<MongoMessageLog> findList(QueryTable queryTable) {
        return mongoMessageLogRepository.find(queryTable);
    }

    public DataTable findPage(QueryTable queryTable) {
        return mongoMessageLogRepository.findPage(queryTable);
    }

    /**
     * 重发发送失败的消息通知
     */
    public void resendFailMessage() {
        QueryTable queryTable = new QueryTable();
        Map<String, Object> param = new HashMap<>();
        param.put("Q_status_S_EQ", StatusType.FAIL.getCode());
        param.put("Q_method_S_NULL", "");
        param.put("Q_retryCount_INT_LT", Convert.toInt(applicationProperties.getValue(ApplicationConstants.SYSTEM_MESSAGE_RETRY), 3));
        queryTable.setParams(param);
        List<MongoMessageLog> messageLogs = mongoMessageLogRepository.find(queryTable);
        if (null != messageLogs && messageLogs.size() > 0) {
            messageLogs.forEach(messageLog -> {
                try {
                    messageLog.setRetryCount(messageLog.getRetryCount() + 1);
                    PayloadDTO payload = new PayloadDTO();
                    payload.setEntity(JsonUtil.toJson(messageLog));
                    String messageType = messageLog.getMessageType();
                    if (StringUtil.isNotEmpty(messageType)) {
                        messageFactory.get(messageType).reSend(payload);
                    } else {
                        messageFactory.get().reSend(payload);
                    }
                } catch (Exception e) {
                    log.error("重发消息失败：{}", e.getMessage());
                } finally {
                    mongoMessageLogRepository.updateById(messageLog.getLogId(), messageLog);
                }
            });
        }
    }
}
